Notebook for working through Chapter 2 of the GGPlot book
library(tidyverse)
[30m── [1mAttaching packages[22m ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──[39m
[30m[32m✓[30m [34mtibble [30m 3.0.0 [32m✓[30m [34mdplyr [30m 0.8.5
[32m✓[30m [34mtidyr [30m 1.0.2 [32m✓[30m [34mstringr[30m 1.4.0
[32m✓[30m [34mreadr [30m 1.3.1 [32m✓[30m [34mforcats[30m 0.5.0
[32m✓[30m [34mpurrr [30m 0.3.3 [39m
[30m── [1mConflicts[22m ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
[31mx[30m [34mdplyr[30m::[32mfilter()[30m masks [34mstats[30m::filter()
[31mx[30m [34mdplyr[30m::[32mlag()[30m masks [34mstats[30m::lag()[39m
names(mpg)
[1] "manufacturer" "model" "displ" "year" "cyl" "trans" "drv" "cty" "hwy" "fl"
[11] "class"
Exercises, Section 2.2
- Convert distance traveled with a fixed amount of fuel (mpg) to fuel consumed over a fixed distance (gpm –> lp100km) to distance traveled with a
function mpg_to_lp100km(mpg){
Error: unexpected symbol in "function mpg_to_lp100km"
- Which manufacturer has the most models in this dataset? Which model has the most variations? Does your answer change if you remove the redundant specification of drivetrain?
Which manufacturer has the most models in this dataset? Toyota
Which model has the most variations? jetta
What if you remove redundant drivetrain?
mpg_data <- mpg %>% mutate(clean_model = str_trim(str_replace(model, c("2wd" = "", "4wd" = "", "awd" = "", "quattro" = ""))))
Error in fix_replacement(replacement) :
argument "replacement" is missing, with no default
Which manufacturer as the most models in this case? Still Toyota, but fewer models
Which model has the most variations? a4
Exercises, Section 2.3
- How would you describe the relationship between cty and hwy? Any concerns about drawing conclusions from this plot? Seems like a pretty direct relationship, hwy generally higher than cty. Seems like less data at higher fuel economy so hard to now how relationship holds. Odd to see “striping”, wonder how values were estimated.

- What does ggplot(mpg, aes(model, manufacturer)) + geom_point() show? Is it useful? How could you modify the data to make it more informative? I have no idea what this is supposed to show, or how it could be useful.

Could instead plot number of models per manufact.

Describe the data, aesthetic mappings and layers used for each of the following plots. You’ll need to guess a little because you haven’t seen all the datasets and functions yet, but use your common sense! See if you can predict what the plot will look like before running the code. – I made these.

Exercises, Section 2.4
- Experiment with the colour, shape and size aesthetics. What happens when you map them to continuous values? What about categorical values? What happens when you use more than one aesthetic in a plot?
–> Map size to displacement, color to drivetrain

plot disp to hwy fuel economy with year

What happens if you map a continuous variable to shape? Why? What happens if you map trans to shape? Why? –> get an error, continuous variable can’t be matched to shape –> map trans to shape get a warning because too many values –> when you map discrete to size (e.g. drv to size), also get a warning


How is drive train related to fuel economy? How is drive train related to engine size and class?
Front wheel drive most fuel efficient, 4 wd least

Could also do with a boxplot

How is drive train related to engine size and class?
Rear wheel drive have largest engine size, front wheel drive smalles. SUVs, pickups largely 4WD. Midsize usually fwd, though some 4WD

#### Exercises, Section 2.5 What happens if you try to facet by a continuous variable like hwy? What about cyl? What’s the key difference?
Facet by highway, get too many graphs (one for each value)

Facet wrap by cyl and more points/graph, because fewer unique values.

Use facetting to explore the 3-way relationship between fuel economy, engine size, and number of cylinders. How does facetting by number of cylinders change your assessement of the relationship between engine size and fuel economy?
–> See above for cty graph, reproduced here for hwy
Both show that the apparent relationship between engine size and fuel economy (smaller engine size –> better fuel economy) is actually largely due to differences in the number of cylinders. (Relationship flat when # of cylinders is held constant, except for small engine sizes, 4 cyl)

Can also see this using aes mapping

Read the documentation for facet_wrap(). What arguments can you use to control how many rows and columns appear in the output? (nrow and n_col)
What does the scales argument to facet_wrap() do? When might you use it? (scales = “fixed”, “free”, “fixed_x”, “fixed_y”. this will control whether the scales are automatically shared across facet rows and columns vs. set by the data in each column. Fixed is default)
Note how this changes the above facet display of engine size, cyl, and fuel economy

Exercises, Section 2.6
What’s the problem with the plot created by ggplot(mpg, aes(cty, hwy)) + geom_point()? Which of the geoms described above is most effective at remedying the problem?

Is the problem the overlapping values? Then we could plot with geom_jitter() instead. (But I don’t really see the problem here… )

One challenge with ggplot(mpg, aes(class, hwy)) + geom_boxplot() is that the ordering of class is alphabetical, which is not terribly useful. How could you change the factor levels to be more informative?

We can order by mean fuel efficiency, setting factor levels by the mean value. It would be nice if there was some way to do this without calculating the group mean explicitly… there is! let’s try fct_reorder

Actually, can do this in one step in ggplot! do by median in this case…

Explore the distribution of the carat variable in the diamonds dataset. What binwidth reveals the most interesting patterns? At smaller binwidths (.25 or .1) can see peak at small carat, and then at each whole carat mark. Actually think .1 looks the best.

Explore the distribution of the price variable in the diamonds data. How does the distribution vary by cut?
–> can you set different binwidths for different layered histograms?
By the averages, Ideal cut less expensive (but also on average smaller). Visualize with a violin plot:
General trend of price vs. carat
I guess a general trend of increasing with carat and cut, but certainly noisy.

Let’s look at a violin plot. First of price x cut

And carat x cut

Try a facet plot to look at all 3 at once.

You now know (at least) three ways to compare the distributions of subgroups: geom_violin(), geom_freqpoly() and the colour aesthetic, or geom_histogram() and facetting. What are the strengths and weaknesses of each approach? What other approaches could you try?
- Violin plot: compact and clean, can only look at 1 variable at a time. Shapes are a complicated abstraction and not suitable for detailed scrutiny.
- Frequency polygon: compact to look at more than 1 subgroup at a time. Interpretation very dependent on binwidth.
- Histogram + facetting: Can be hard to compare across all subgroups. Interpretation dependent on binwidth.
Read the documentation for geom_bar(). What does the weight aesthetic do? The weight aesthetic calculates a sum of weights instead of a subgroup count.
Using the techniques already discussed in this chapter, come up with three ways to visualise a 2d categorical distribution. Try them out by visualising the distribution of model and manufacturer, trans and class, and cyl and trans.
- Model and manufacturer – I still don’t really understand what this is. Again, going to use count of models, as above.

- trans and class


- cyl and trans

LS0tCnRpdGxlOiAiR0dQbG90IENoYXB0ZXIgMiIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogIkhhbm5haCBHZWxtYW4iCmRhdGU6ICIyMDIwLTA0LTA4IgotLS0KCk5vdGVib29rIGZvciB3b3JraW5nIHRocm91Z2ggQ2hhcHRlciAyIG9mIHRoZSBHR1Bsb3QgYm9vayAKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpIApsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgoKYGBge3J9CmhlYWQobXBnKQpgYGAKYGBge3J9Cm5hbWVzKG1wZykKYGBgCgojIyMjIEV4ZXJjaXNlcywgU2VjdGlvbiAyLjIgCgozLiBDb252ZXJ0IGRpc3RhbmNlIHRyYXZlbGVkIHdpdGggYSBmaXhlZCBhbW91bnQgb2YgZnVlbCAobXBnKSB0byBmdWVsIGNvbnN1bWVkIG92ZXIgYSBmaXhlZCBkaXN0YW5jZSAoZ3BtIC0tPiBscDEwMGttKSB0byBkaXN0YW5jZSB0cmF2ZWxlZCB3aXRoIGEgCmBgYHtyfQptcGdfdG9fbHAxMDBrbSA8LSBmdW5jdGlvbihtcGcpeyAKICAjY29udmVyc2lvbiBnYWxsb25zIHRvIGxpdGVycyAKICBsaXRfcF9nYWwgPC0gMy43OCAKICAjY29udmVyc2lvbiBtaWxlcyB0byAxIGttIAogIG1pbF9wX2ttIDwtIC42MgogIAogIGxwMTAwa20gPC0gMS9tcGcgKiBsaXRfcF9nYWwgKiBtaWxfcF9rbSAqMTAwIAogIHJldHVybihscDEwMGttKSAKfQoKbXBnX2RhdGEgPC0gbXBnICU+JSBtdXRhdGUoaHd5X2xwMTAwa20gPSBtcGdfdG9fbHAxMDBrbShod3kpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R5X2xwMTAwa20gPSBtcGdfdG9fbHAxMDBrbShjdHkpKQoKYGBgCgo0LiBXaGljaCBtYW51ZmFjdHVyZXIgaGFzIHRoZSBtb3N0IG1vZGVscyBpbiB0aGlzIGRhdGFzZXQ/IFdoaWNoIG1vZGVsIGhhcyB0aGUgbW9zdCB2YXJpYXRpb25zPyBEb2VzIHlvdXIgYW5zd2VyIGNoYW5nZSBpZiB5b3UgcmVtb3ZlIHRoZSByZWR1bmRhbnQgc3BlY2lmaWNhdGlvbiBvZiBkcml2ZXRyYWluPyAKCldoaWNoIG1hbnVmYWN0dXJlciBoYXMgdGhlIG1vc3QgbW9kZWxzIGluIHRoaXMgZGF0YXNldD8gVG95b3RhIApgYGB7cn0KbXBnICU+JSBncm91cF9ieShtYW51ZmFjdHVyZXIpICU+JSBzdW1tYXJpemUobm1vZGVscyA9IG5fZGlzdGluY3QobW9kZWwpKSAlPiUgYXJyYW5nZSgtbm1vZGVscykKYGBgCgpXaGljaCBtb2RlbCBoYXMgdGhlIG1vc3QgdmFyaWF0aW9ucz8gamV0dGEKYGBge3J9Cm1wZyAlPiUgZ3JvdXBfYnkobW9kZWwpICU+JSBzdW1tYXJpemUobnZhciA9IG4oKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnZhcl9ub3RfeWVhciA9IG5fZGlzdGluY3QoZGlzcGwsIGN5bCwgdHJhbnMsIGRydikpICU+JSAKICBhcnJhbmdlKC1udmFyX25vdF95ZWFyKQpgYGAKV2hhdCBpZiB5b3UgcmVtb3ZlIHJlZHVuZGFudCBkcml2ZXRyYWluPyAKCmBgYHtyfQojdGhpcyBmdW5jdGlvbiBkb2Vzbid0IHdvcmsgYXMgZXhwZWN0ZWQgLSByZXR1cm5zIHNhbWUgKGxhc3QpIHZhbHVlIGZvciBhbGwuIHdoeT8gCnJlbW92ZV9kcnYgPC0gZnVuY3Rpb24obW9kZWxuYW1lKXsKICAjcmVtb3ZlIGRyaXZldHJhaW4gc3BlY2lmaWNhdGlvbiBpZiBpbmNsdWRlZCBpbiBtb2RlbCBuYW1lIAogIG1vZGVsX2FyciA9IHN0cnNwbGl0KG1vZGVsbmFtZSwgIiAiKSAKICAKICBuID0gbGVuZ3RoKG1vZGVsX2FycikKICAjaWYgdGhlIGxlbmd0aCBpcyAxLCByZXR1cm4gbW9kZWxuYW1lIGFzIGJlZm9yZSAKICBpZihuID09IDEpIHsKICAgIHJldHVybihtb2RlbG5hbWUpCiAgfSBlbHNlIGlmKG1vZGVsX2FycltuXSAlaW4lIGMoJzR3ZCcsICcyd2QnLCAncXVhdHRybycsICdhd2QnKSkgewogICAgcmV0dXJuKHBhc3RlKG1vZGVsX2FyclsxOm4tMV0pKQogIH0gZWxzZSB7IAogICAgcmV0dXJuKG1vZGVsbmFtZSkgfQogIAp9CgptcGdfZGF0YSA8LSBtcGcgJT4lIG11dGF0ZShjbGVhbl9tb2RlbCA9IHN0cl90cmltKHN0cl9yZXBsYWNlX2FsbChtb2RlbCwgYygiMndkIiA9ICIiLCAiNHdkIiA9ICIiLCAiYXdkIiA9ICIiLCAicXVhdHRybyIgPSAiIikpKSkKYGBgCgpXaGljaCBtYW51ZmFjdHVyZXIgYXMgdGhlIG1vc3QgbW9kZWxzIGluIHRoaXMgY2FzZT8gU3RpbGwgVG95b3RhLCBidXQgZmV3ZXIgbW9kZWxzIApgYGB7cn0KbXBnX2RhdGEgJT4lIGdyb3VwX2J5KG1hbnVmYWN0dXJlcikgJT4lIHN1bW1hcml6ZShubW9kZWxzID0gbl9kaXN0aW5jdChjbGVhbl9tb2RlbCkpICU+JSBhcnJhbmdlKC1ubW9kZWxzKQpgYGAKV2hpY2ggbW9kZWwgaGFzIHRoZSBtb3N0IHZhcmlhdGlvbnM/IGE0IApgYGB7cn0KbXBnX2RhdGEgJT4lIGdyb3VwX2J5KGNsZWFuX21vZGVsKSAlPiUgCiAgc3VtbWFyaXplKG52YXIgPSBuKCksIAogICAgICAgICAgICBudmFyX25vdF95ZWFyID0gbl9kaXN0aW5jdChkaXNwbCwgY3lsLCB0cmFucywgZHJ2KSkgJT4lIAogIGFycmFuZ2UoLW52YXJfbm90X3llYXIpCgojbXBnX2RhdGEgJT4lIGZpbHRlcihjbGVhbl9tb2RlbCA9PSAnYTQnKSAlPiUgYXJyYW5nZShkcnYsIHRyYW5zLCBjeWwpCiNieSBpbnNwZWN0aW9uLCBzYW1lIGNvbmZpZyBkb2VzIG5vdCBhcHBlYXIgcmVwZWF0ZWQgYnkgeWVhci4gCmBgYAoKIyMjIyBFeGVyY2lzZXMsIFNlY3Rpb24gMi4zIAoxLiBIb3cgd291bGQgeW91IGRlc2NyaWJlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBjdHkgYW5kIGh3eT8gQW55IGNvbmNlcm5zIGFib3V0IGRyYXdpbmcgY29uY2x1c2lvbnMgZnJvbSB0aGlzIHBsb3Q/IApTZWVtcyBsaWtlIGEgcHJldHR5IGRpcmVjdCByZWxhdGlvbnNoaXAsIGh3eSBnZW5lcmFsbHkgaGlnaGVyIHRoYW4gY3R5LiBTZWVtcyBsaWtlIGxlc3MgZGF0YSBhdCBoaWdoZXIgZnVlbCBlY29ub215IHNvIGhhcmQgdG8gbm93IGhvdyByZWxhdGlvbnNoaXAgaG9sZHMuIE9kZCB0byBzZWUgInN0cmlwaW5nIiwgd29uZGVyIGhvdyB2YWx1ZXMgd2VyZSBlc3RpbWF0ZWQuIAoKYGBge3J9CmdncGxvdChtcGcsIGFlcyhod3ksIGN0eSkpICsgCiAgZ2VvbV9wb2ludCgpCmBgYAoKCjIuIFdoYXQgZG9lcyBnZ3Bsb3QobXBnLCBhZXMobW9kZWwsIG1hbnVmYWN0dXJlcikpICsgZ2VvbV9wb2ludCgpIHNob3c/IElzIGl0IHVzZWZ1bD8gSG93IGNvdWxkIHlvdSBtb2RpZnkgdGhlIGRhdGEgdG8gbWFrZSBpdCBtb3JlIGluZm9ybWF0aXZlPwpJIGhhdmUgbm8gaWRlYSB3aGF0IHRoaXMgaXMgc3VwcG9zZWQgdG8gc2hvdywgb3IgaG93IGl0IGNvdWxkIGJlIHVzZWZ1bC4gCmBgYHtyfQpnZ3Bsb3QobXBnLCBhZXMobW9kZWwsIG1hbnVmYWN0dXJlcikpICsgCiAgZ2VvbV9wb2ludCgpCmBgYAoKQ291bGQgaW5zdGVhZCBwbG90IG51bWJlciBvZiBtb2RlbHMgcGVyIG1hbnVmYWN0LiAKYGBge3J9Cm1wZ19kYXRhICU+JSBncm91cF9ieShjbGVhbl9tb2RlbCkgJT4lIGdyb3VwX2J5KG1hbnVmYWN0dXJlcikgJT4lIHN1bW1hcml6ZShubW9kZWxzID0gbl9kaXN0aW5jdChjbGVhbl9tb2RlbCkpICU+JSAKICBnZ3Bsb3QoYWVzKG1hbnVmYWN0dXJlciwgbm1vZGVscykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikKYGBgCgpEZXNjcmliZSB0aGUgZGF0YSwgYWVzdGhldGljIG1hcHBpbmdzIGFuZCBsYXllcnMgdXNlZCBmb3IgZWFjaCBvZiB0aGUgZm9sbG93aW5nIHBsb3RzLiBZb3XigJlsbCBuZWVkIHRvIGd1ZXNzIGEgbGl0dGxlIGJlY2F1c2UgeW91IGhhdmVu4oCZdCBzZWVuIGFsbCB0aGUgZGF0YXNldHMgYW5kIGZ1bmN0aW9ucyB5ZXQsIGJ1dCB1c2UgeW91ciBjb21tb24gc2Vuc2UhIFNlZSBpZiB5b3UgY2FuIHByZWRpY3Qgd2hhdCB0aGUgcGxvdCB3aWxsIGxvb2sgbGlrZSBiZWZvcmUgcnVubmluZyB0aGUgY29kZS4KLS0gSSBtYWRlIHRoZXNlLiAKYGBge3J9CmdncGxvdChtcGcsIGFlcyhjdHkpKSArIGdlb21faGlzdG9ncmFtKCkKYGBgCgojIyMjIEV4ZXJjaXNlcywgU2VjdGlvbiAyLjQgCjEpIEV4cGVyaW1lbnQgd2l0aCB0aGUgY29sb3VyLCBzaGFwZSBhbmQgc2l6ZSBhZXN0aGV0aWNzLiBXaGF0IGhhcHBlbnMgd2hlbiB5b3UgbWFwIHRoZW0gdG8gY29udGludW91cyB2YWx1ZXM/IFdoYXQgYWJvdXQgY2F0ZWdvcmljYWwgdmFsdWVzPyBXaGF0IGhhcHBlbnMgd2hlbiB5b3UgdXNlIG1vcmUgdGhhbiBvbmUgYWVzdGhldGljIGluIGEgcGxvdD8KCi0tPiBNYXAgc2l6ZSB0byBkaXNwbGFjZW1lbnQsIGNvbG9yIHRvIGRyaXZldHJhaW4gCmBgYHtyfQpnZ3Bsb3QobXBnLCBhZXMoaHd5LCBjdHksIHNpemUgPSBkaXNwbCwgY29sb3IgPSBkcnYpKSArIGdlb21fcG9pbnQoKQpgYGAKCnBsb3QgZGlzcCB0byBod3kgZnVlbCBlY29ub215IHdpdGggeWVhcgpgYGB7cn0KZ2dwbG90KG1wZywgYWVzKGRpc3BsLCBod3ksIGNvbG9yID0gYXMuY2hhcmFjdGVyKHllYXIpKSkgKyBnZW9tX3BvaW50KCkKYGBgCgpXaGF0IGhhcHBlbnMgaWYgeW91IG1hcCBhIGNvbnRpbnVvdXMgdmFyaWFibGUgdG8gc2hhcGU/IFdoeT8gV2hhdCBoYXBwZW5zIGlmIHlvdSBtYXAgdHJhbnMgdG8gc2hhcGU/IFdoeT8KLS0+IGdldCBhbiBlcnJvciwgY29udGludW91cyB2YXJpYWJsZSBjYW4ndCBiZSBtYXRjaGVkIHRvIHNoYXBlIAotLT4gbWFwIHRyYW5zIHRvIHNoYXBlIGdldCBhIHdhcm5pbmcgYmVjYXVzZSB0b28gbWFueSB2YWx1ZXMgCi0tPiB3aGVuIHlvdSBtYXAgZGlzY3JldGUgdG8gc2l6ZSAoZS5nLiBkcnYgdG8gc2l6ZSksIGFsc28gZ2V0IGEgd2FybmluZwpgYGB7cn0KZ2dwbG90KG1wZywgYWVzKGh3eSwgY3R5LCBzaGFwZSA9IHRyYW5zKSkgKyBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KZ2dwbG90KG1wZywgYWVzKGh3eSwgY3R5LCBzaXplID0gZHJ2KSkgKyBnZW9tX3BvaW50KCkKCmBgYAoKSG93IGlzIGRyaXZlIHRyYWluIHJlbGF0ZWQgdG8gZnVlbCBlY29ub215PyBIb3cgaXMgZHJpdmUgdHJhaW4gcmVsYXRlZCB0byBlbmdpbmUgc2l6ZSBhbmQgY2xhc3M/CgpGcm9udCB3aGVlbCBkcml2ZSBtb3N0IGZ1ZWwgZWZmaWNpZW50LCA0IHdkIGxlYXN0IApgYGB7cn0KbXBnICU+JSBncm91cF9ieShkcnYpICU+JSBzdW1tYXJpemUoYXZnX2h3eSA9IG1lYW4oaHd5KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkX2h3eSA9IHNkKGh3eSkpICU+JSAKICBnZ3Bsb3QoYWVzKGRydiwgYXZnX2h3eSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gYXZnX2h3eSAtIHNkX2h3eSwgeW1heCA9IGF2Z19od3kgKyBzZF9od3ksIHdpZHRoPS4yKSkKYGBgCgpDb3VsZCBhbHNvIGRvIHdpdGggYSBib3hwbG90CmBgYHtyfQpnZ3Bsb3QobXBnLCBhZXMoZHJ2LCBod3kpKSArIAogIGdlb21fYm94cGxvdCgpCmBgYAoKSG93IGlzIGRyaXZlIHRyYWluIHJlbGF0ZWQgdG8gZW5naW5lIHNpemUgYW5kIGNsYXNzPwoKUmVhciB3aGVlbCBkcml2ZSBoYXZlIGxhcmdlc3QgZW5naW5lIHNpemUsIGZyb250IHdoZWVsIGRyaXZlIHNtYWxsZXMuIFNVVnMsIHBpY2t1cHMgbGFyZ2VseSA0V0QuIE1pZHNpemUgdXN1YWxseSBmd2QsIHRob3VnaCBzb21lIDRXRApgYGB7cn0KZ2dwbG90KG1wZywgYWVzKGRydiwgZGlzcGwsIGNvbG9yID0gY2xhc3MpKSArCiAgZ2VvbV9wb2ludCgpCmBgYAogCiAjIyMjIEV4ZXJjaXNlcywgU2VjdGlvbiAyLjUgCldoYXQgaGFwcGVucyBpZiB5b3UgdHJ5IHRvIGZhY2V0IGJ5IGEgY29udGludW91cyB2YXJpYWJsZSBsaWtlIGh3eT8gV2hhdCBhYm91dCBjeWw/IFdoYXTigJlzIHRoZSBrZXkgZGlmZmVyZW5jZT8KCkZhY2V0IGJ5IGhpZ2h3YXksIGdldCB0b28gbWFueSBncmFwaHMgKG9uZSBmb3IgZWFjaCB2YWx1ZSkKYGBge3J9CmdncGxvdChtcGcsIGFlcyhkaXNwbCwgY3R5KSkgKwogIGdlb21fcG9pbnQoKSArIAogIGZhY2V0X3dyYXAofmh3eSkKYGBgCgpGYWNldCB3cmFwIGJ5IGN5bCBhbmQgbW9yZSBwb2ludHMvZ3JhcGgsIGJlY2F1c2UgZmV3ZXIgdW5pcXVlIHZhbHVlcy4gCgpgYGB7cn0KZ2dwbG90KG1wZywgYWVzKGRpc3BsLCBjdHkpKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfd3JhcCh+Y3lsKQpgYGAKClVzZSBmYWNldHRpbmcgdG8gZXhwbG9yZSB0aGUgMy13YXkgcmVsYXRpb25zaGlwIGJldHdlZW4gZnVlbCBlY29ub215LCBlbmdpbmUgc2l6ZSwgYW5kIG51bWJlciBvZiBjeWxpbmRlcnMuIEhvdyBkb2VzIGZhY2V0dGluZyBieSBudW1iZXIgb2YgY3lsaW5kZXJzIGNoYW5nZSB5b3VyIGFzc2Vzc2VtZW50IG9mIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBlbmdpbmUgc2l6ZSBhbmQgZnVlbCBlY29ub215PwoKLS0+IFNlZSBhYm92ZSBmb3IgY3R5IGdyYXBoLCByZXByb2R1Y2VkIGhlcmUgZm9yIGh3eSAKCkJvdGggc2hvdyB0aGF0IHRoZSBhcHBhcmVudCByZWxhdGlvbnNoaXAgYmV0d2VlbiBlbmdpbmUgc2l6ZSBhbmQgZnVlbCBlY29ub215IChzbWFsbGVyIGVuZ2luZSBzaXplIC0tPiBiZXR0ZXIgZnVlbCBlY29ub215KSBpcyBhY3R1YWxseSBsYXJnZWx5IGR1ZSB0byBkaWZmZXJlbmNlcyBpbiB0aGUgbnVtYmVyIG9mIGN5bGluZGVycy4gKFJlbGF0aW9uc2hpcCBmbGF0IHdoZW4gIyBvZiBjeWxpbmRlcnMgaXMgaGVsZCBjb25zdGFudCwgZXhjZXB0IGZvciBzbWFsbCBlbmdpbmUgc2l6ZXMsIDQgY3lsKSAKCmBgYHtyfQpnZ3Bsb3QobXBnLCBhZXMoZGlzcGwsIGh3eSkpICsKICBnZW9tX3BvaW50KCkgKyAKICBmYWNldF93cmFwKH5jeWwpCmBgYAoKQ2FuIGFsc28gc2VlIHRoaXMgdXNpbmcgYWVzIG1hcHBpbmcgCmBgYHtyfQpnZ3Bsb3QobXBnLCBhZXMoZGlzcGwsIGh3eSwgY29sb3IgPSBhcy5jaGFyYWN0ZXIoY3lsKSkpICsgZ2VvbV9wb2ludCgpCgpgYGAKCgpSZWFkIHRoZSBkb2N1bWVudGF0aW9uIGZvciBmYWNldF93cmFwKCkuIFdoYXQgYXJndW1lbnRzIGNhbiB5b3UgdXNlIHRvIGNvbnRyb2wgaG93IG1hbnkgcm93cyBhbmQgY29sdW1ucyBhcHBlYXIgaW4gdGhlIG91dHB1dD8gKG5yb3cgYW5kIG5fY29sKQoKV2hhdCBkb2VzIHRoZSBzY2FsZXMgYXJndW1lbnQgdG8gZmFjZXRfd3JhcCgpIGRvPyBXaGVuIG1pZ2h0IHlvdSB1c2UgaXQ/IChzY2FsZXMgPSAiZml4ZWQiLCAiZnJlZSIsICJmaXhlZF94IiwgImZpeGVkX3kiLiB0aGlzIHdpbGwgY29udHJvbCB3aGV0aGVyIHRoZSBzY2FsZXMgYXJlIGF1dG9tYXRpY2FsbHkgc2hhcmVkIGFjcm9zcyBmYWNldCByb3dzIGFuZCBjb2x1bW5zIHZzLiBzZXQgYnkgdGhlIGRhdGEgaW4gZWFjaCBjb2x1bW4uIEZpeGVkIGlzIGRlZmF1bHQpIAoKTm90ZSBob3cgdGhpcyBjaGFuZ2VzIHRoZSBhYm92ZSBmYWNldCBkaXNwbGF5IG9mIGVuZ2luZSBzaXplLCBjeWwsIGFuZCBmdWVsIGVjb25vbXkKYGBge3J9CmdncGxvdChtcGcsIGFlcyhkaXNwbCwgaHd5KSkgKwogIGdlb21fcG9pbnQoKSArIAogIGZhY2V0X3dyYXAofmN5bCwgc2NhbGVzID0gImZyZWUiKQpgYGAKCiMjIyMgRXhlcmNpc2VzLCBTZWN0aW9uIDIuNgoKV2hhdOKAmXMgdGhlIHByb2JsZW0gd2l0aCB0aGUgcGxvdCBjcmVhdGVkIGJ5IGdncGxvdChtcGcsIGFlcyhjdHksIGh3eSkpICsgZ2VvbV9wb2ludCgpPyBXaGljaCBvZiB0aGUgZ2VvbXMgZGVzY3JpYmVkIGFib3ZlIGlzIG1vc3QgZWZmZWN0aXZlIGF0IHJlbWVkeWluZyB0aGUgcHJvYmxlbT8KYGBge3J9CmdncGxvdChtcGcsIGFlcyhjdHksIGh3eSkpICsgZ2VvbV9wb2ludCgpCmBgYAoKSXMgdGhlIHByb2JsZW0gdGhlIG92ZXJsYXBwaW5nIHZhbHVlcz8gVGhlbiB3ZSBjb3VsZCBwbG90IHdpdGggZ2VvbV9qaXR0ZXIoKSBpbnN0ZWFkLgooQnV0IEkgZG9uJ3QgcmVhbGx5IHNlZSB0aGUgcHJvYmxlbSBoZXJlLi4uICkKYGBge3J9CmdncGxvdChtcGcsIGFlcyhjdHksIGh3eSkpICsgZ2VvbV9qaXR0ZXIoKQpgYGAKCk9uZSBjaGFsbGVuZ2Ugd2l0aCBnZ3Bsb3QobXBnLCBhZXMoY2xhc3MsIGh3eSkpICsgZ2VvbV9ib3hwbG90KCkgaXMgdGhhdCB0aGUgb3JkZXJpbmcgb2YgY2xhc3MgaXMgYWxwaGFiZXRpY2FsLCB3aGljaCBpcyBub3QgdGVycmlibHkgdXNlZnVsLiBIb3cgY291bGQgeW91IGNoYW5nZSB0aGUgZmFjdG9yIGxldmVscyB0byBiZSBtb3JlIGluZm9ybWF0aXZlPwoKYGBge3J9CmdncGxvdChtcGcsIGFlcyhjbGFzcywgaHd5KSkgKyBnZW9tX2JveHBsb3QoKQpgYGAKIAogV2UgY2FuIG9yZGVyIGJ5IG1lYW4gZnVlbCBlZmZpY2llbmN5LCBzZXR0aW5nIGZhY3RvciBsZXZlbHMgYnkgdGhlIG1lYW4gdmFsdWUuIAogSXQgd291bGQgYmUgbmljZSBpZiB0aGVyZSB3YXMgc29tZSB3YXkgdG8gZG8gdGhpcyB3aXRob3V0IGNhbGN1bGF0aW5nIHRoZSBncm91cCBtZWFuIGV4cGxpY2l0bHkuLi4gCiB0aGVyZSBpcyEgbGV0J3MgdHJ5IGZjdF9yZW9yZGVyCiAKYGBge3J9Cm1wZyAlPiUgCiAgbXV0YXRlKGNsYXNzID0gZmN0X3Jlb3JkZXIoY2xhc3MsIGh3eSwgLmZ1bj0nbWVhbicpKSAlPiUgCiAgZ2dwbG90KGFlcyhjbGFzcywgaHd5KSkgKyBnZW9tX2JveHBsb3QoKQpgYGAKCkFjdHVhbGx5LCBjYW4gZG8gdGhpcyBpbiBvbmUgc3RlcCBpbiBnZ3Bsb3QhIGRvIGJ5IG1lZGlhbiBpbiB0aGlzIGNhc2UuLi4gCmBgYHtyfQpnZ3Bsb3QobXBnLCBhZXMocmVvcmRlcihjbGFzcywgaHd5LCBtZWRpYW4pLCBod3kpKSArIGdlb21fYm94cGxvdCgpCmBgYAoKRXhwbG9yZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBjYXJhdCB2YXJpYWJsZSBpbiB0aGUgZGlhbW9uZHMgZGF0YXNldC4gV2hhdCBiaW53aWR0aCByZXZlYWxzIHRoZSBtb3N0IGludGVyZXN0aW5nIHBhdHRlcm5zPwpBdCBzbWFsbGVyIGJpbndpZHRocyAoLjI1IG9yIC4xKSBjYW4gc2VlIHBlYWsgYXQgc21hbGwgY2FyYXQsIGFuZCB0aGVuIGF0IGVhY2ggd2hvbGUgY2FyYXQgbWFyay4gCkFjdHVhbGx5IHRoaW5rIC4xIGxvb2tzIHRoZSBiZXN0LiAKYGBge3J9CmdncGxvdChkaWFtb25kcywgYWVzKGNhcmF0KSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4xKQpgYGAKCkV4cGxvcmUgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcHJpY2UgdmFyaWFibGUgaW4gdGhlIGRpYW1vbmRzIGRhdGEuIEhvdyBkb2VzIHRoZSBkaXN0cmlidXRpb24gdmFyeSBieSBjdXQ/CgotLT4gY2FuIHlvdSBzZXQgZGlmZmVyZW50IGJpbndpZHRocyBmb3IgZGlmZmVyZW50IGxheWVyZWQgaGlzdG9ncmFtcz8gCmBgYHtyfQpkaWFtb25kcyAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgCiAgc3VtbWFyaXplKGF2Z19wcmljZSA9IG1lYW4ocHJpY2UpLCAKICAgICAgICAgICAgYXZnX2NhcmF0ID0gbWVhbihjYXJhdCksIAogICAgICAgICAgICBudW1fcmVjb3JkcyA9IG4oKSkKYGBgCgpCeSB0aGUgYXZlcmFnZXMsIElkZWFsIGN1dCBsZXNzIGV4cGVuc2l2ZSAoYnV0IGFsc28gb24gYXZlcmFnZSBzbWFsbGVyKS4gVmlzdWFsaXplIHdpdGggYSB2aW9saW4gcGxvdDogCgpHZW5lcmFsIHRyZW5kIG9mIHByaWNlIHZzLiBjYXJhdCAKCkkgZ3Vlc3MgYSBnZW5lcmFsIHRyZW5kIG9mIGluY3JlYXNpbmcgd2l0aCBjYXJhdCBhbmQgY3V0LCBidXQgY2VydGFpbmx5IG5vaXN5LiAKCmBgYHtyfQpnZ3Bsb3QoZGlhbW9uZHMsIGFlcyhjYXJhdCwgcHJpY2UsIGNvbG9yID0gY3V0KSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBnZW9tX3Ntb290aCgpCmBgYAoKTGV0J3MgbG9vayBhdCBhIHZpb2xpbiBwbG90LiBGaXJzdCBvZiBwcmljZSB4IGN1dCAKYGBge3J9CmdncGxvdChkaWFtb25kcywgYWVzKGN1dCwgcHJpY2UpKSArIAogIGdlb21fdmlvbGluKCkKCmBgYAoKQW5kIGNhcmF0IHggY3V0IAoKYGBge3J9CmdncGxvdChkaWFtb25kcywgYWVzKGN1dCwgY2FyYXQpKSArIAogIGdlb21fdmlvbGluKCkKCmBgYAoKVHJ5IGEgZmFjZXQgcGxvdCB0byBsb29rIGF0IGFsbCAzIGF0IG9uY2UuIApgYGB7cn0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoY2FyYXQsIHByaWNlKSkgKwogIGdlb21fcG9pbnQoKSArIAogIGZhY2V0X3dyYXAofmN1dCkKYGBgCgpZb3Ugbm93IGtub3cgKGF0IGxlYXN0KSB0aHJlZSB3YXlzIHRvIGNvbXBhcmUgdGhlIGRpc3RyaWJ1dGlvbnMgb2Ygc3ViZ3JvdXBzOiBnZW9tX3Zpb2xpbigpLCBnZW9tX2ZyZXFwb2x5KCkgYW5kIHRoZSBjb2xvdXIgYWVzdGhldGljLCBvciBnZW9tX2hpc3RvZ3JhbSgpIGFuZCBmYWNldHRpbmcuIFdoYXQgYXJlIHRoZSBzdHJlbmd0aHMgYW5kIHdlYWtuZXNzZXMgb2YgZWFjaCBhcHByb2FjaD8gV2hhdCBvdGhlciBhcHByb2FjaGVzIGNvdWxkIHlvdSB0cnk/CgotIFZpb2xpbiBwbG90OiBjb21wYWN0IGFuZCBjbGVhbiwgY2FuIG9ubHkgbG9vayBhdCAxIHZhcmlhYmxlIGF0IGEgdGltZS4gU2hhcGVzIGFyZSBhIGNvbXBsaWNhdGVkIGFic3RyYWN0aW9uIGFuZCBub3Qgc3VpdGFibGUgZm9yIGRldGFpbGVkIHNjcnV0aW55LiAKLSBGcmVxdWVuY3kgcG9seWdvbjogY29tcGFjdCB0byBsb29rIGF0IG1vcmUgdGhhbiAxIHN1Ymdyb3VwIGF0IGEgdGltZS4gSW50ZXJwcmV0YXRpb24gdmVyeSBkZXBlbmRlbnQgb24gYmlud2lkdGguIAotIEhpc3RvZ3JhbSArIGZhY2V0dGluZzogQ2FuIGJlIGhhcmQgdG8gY29tcGFyZSBhY3Jvc3MgYWxsIHN1Ymdyb3Vwcy4gSW50ZXJwcmV0YXRpb24gZGVwZW5kZW50IG9uIGJpbndpZHRoLiAKCgpSZWFkIHRoZSBkb2N1bWVudGF0aW9uIGZvciBnZW9tX2JhcigpLiBXaGF0IGRvZXMgdGhlIHdlaWdodCBhZXN0aGV0aWMgZG8/IFRoZSB3ZWlnaHQgYWVzdGhldGljIGNhbGN1bGF0ZXMgYSBzdW0gb2Ygd2VpZ2h0cyBpbnN0ZWFkIG9mIGEgc3ViZ3JvdXAgY291bnQuIAoKVXNpbmcgdGhlIHRlY2huaXF1ZXMgYWxyZWFkeSBkaXNjdXNzZWQgaW4gdGhpcyBjaGFwdGVyLCBjb21lIHVwIHdpdGggdGhyZWUgd2F5cyB0byB2aXN1YWxpc2UgYSAyZCBjYXRlZ29yaWNhbCBkaXN0cmlidXRpb24uIFRyeSB0aGVtIG91dCBieSB2aXN1YWxpc2luZyB0aGUgZGlzdHJpYnV0aW9uIG9mIG1vZGVsIGFuZCBtYW51ZmFjdHVyZXIsIHRyYW5zIGFuZCBjbGFzcywgYW5kIGN5bCBhbmQgdHJhbnMuCgoxKSBNb2RlbCBhbmQgbWFudWZhY3R1cmVyIAotLSBJIHN0aWxsIGRvbid0IHJlYWxseSB1bmRlcnN0YW5kIHdoYXQgdGhpcyBpcy4gQWdhaW4sIGdvaW5nIHRvIHVzZSBjb3VudCBvZiBtb2RlbHMsIGFzIGFib3ZlLiAgCmBgYHtyfQptcGdfZGF0YSAlPiUgZ3JvdXBfYnkoY2xlYW5fbW9kZWwpICU+JSBncm91cF9ieShtYW51ZmFjdHVyZXIpICU+JSBzdW1tYXJpemUobm1vZGVscyA9IG5fZGlzdGluY3QoY2xlYW5fbW9kZWwpKSAlPiUgCiAgZ2dwbG90KGFlcyhtYW51ZmFjdHVyZXIsIG5tb2RlbHMpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpCmBgYAoKMikgdHJhbnMgYW5kIGNsYXNzCmBgYHtyfQpnZ3Bsb3QobXBnX2RhdGEsIGFlcyhjbGFzcykpICsKICBnZW9tX2JhcigpICsKICBmYWNldF93cmFwKH50cmFucykKCmBgYAoKYGBge3J9CmdncGxvdChtcGdfZGF0YSwgYWVzKGNsYXNzLCBmaWxsID0gdHJhbnMpKSArCiAgZ2VvbV9iYXIoKSAKYGBgCgoKMykgY3lsIGFuZCB0cmFucwpgYGB7cn0KZ2dwbG90KG1wZ19kYXRhLCBhZXModHJhbnMsIGN5bCwgY29sb3IgPSB0cmFucykpICsKICBnZW9tX2ppdHRlcigpCmBgYAoK